/*
 * Copyright (c) 2020 - present, Inspur Genersoft Co., Ltd.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package io.iec.edp.caf.tenancy.core.service;

import io.iec.edp.caf.tenancy.api.entity.SuDbMapping;
import io.iec.edp.caf.tenancy.api.service.DbMappingService;
import io.iec.edp.caf.tenancy.core.TenantCache;
import io.iec.edp.caf.tenancy.core.repository.SuDbMappingRepository;
import io.iec.edp.caf.tenancy.core.utils.DataValidator;
import lombok.var;

import java.util.List;
import java.util.stream.Collectors;

/**
 * 服务单元~连接字符串映射管理类
 *
 * @author Hey Law
 * @create 2019年8月19日$
 */
public class DbMappingManager implements DbMappingService {

    private final SuDbMappingRepository repository;

    private final TenantCache tenantCache;

//    private ConcurrentHashMap<String, DbConnection> connInfos = new ConcurrentHashMap<>();

    public DbMappingManager(SuDbMappingRepository repository, TenantCache tenantCache)
    {
        this.repository = repository;
        this.tenantCache = tenantCache;
    }

    /// <summary>
    /// 根据租户标识获取所有连接信息
    /// </summary>
    /// <param name="tenantId">租户标识</param>
    /// <returns>所有连接信息</returns>
    /**
     * 根据应用实例获取所有服务单元连接映射信息
     *
     * @param appInstanceId 应用实例
     * @return 服务单元连接映射信息
     * @Date: 2019/8/21
    */
    public List<SuDbMapping>    getAll(String appInstanceId)
    {
        DataValidator.checkForEmptyString(appInstanceId, "appInstanceId");
        return this.repository.findAllByAppInstanceId(appInstanceId);
    }

    /**
     * 根据应用实例和服务单元获取连接映射信息
     *
     * @param appInstanceId 应用实例
     * @param su 服务单元标识
     * @return
     * @Date: 2019/8/21
    */
    public SuDbMapping get(String appInstanceId,String su)
    {
        DataValidator.checkForEmptyString(appInstanceId, "appInstanceId");
        DataValidator.checkForEmptyString(su, "su");
        String cacheKey = this.getCacheKey(appInstanceId);
        SuDbMapping mapping = tenantCache.hashGet(cacheKey, su, SuDbMapping.class);

        if (mapping == null)
        {
            //List<SuDbMapping> mappings = this.repository.findByAppInstanceIdAndSu(appInstanceId, su);

            //获取该应用实例下所有Su映射关系，再忽略大小写与su进行筛选
            List<SuDbMapping> mappings = this.getAll(appInstanceId);
            if(mappings!=null)
                mappings = mappings.stream().
                        filter(s-> s.getSu().equalsIgnoreCase(su)||s.getSu().equals("*")).collect(Collectors.toList());
            if(mappings!=null && mappings.size()>1)
                mapping = mappings.stream().
                        filter(s-> s.getSu().equalsIgnoreCase(su)).findFirst().get();
            else if(mappings!=null && mappings.size()==1)
                mapping = mappings.get(0);

            if (mapping != null)
            {
                tenantCache.hashSet(cacheKey, su, mapping);
            }
        }
        return mapping;
    }

    /**
     * 添加
     *
     * @param appInstanceId 应用实例
     * @param mappings 应用实例和服务单元获取连接映射信息
     * @return
     * @Date: 2019/8/21
     */
    public void add(String appInstanceId, List<SuDbMapping> mappings)
    {
        DataValidator.checkForEmptyString(appInstanceId, "appInstanceId");
        DataValidator.checkForNullReference(mappings, "List<SUDBMapping>");

        String cacheKey = this.getCacheKey(appInstanceId);
        this.repository.saveAll(mappings);

        for ( SuDbMapping item : mappings )
        {
            tenantCache.hashRemove(cacheKey, item.getSu());
        }

    }

    /**
     * 更新租户信息
     *
     * @param appInstanceId 应用实例
     * @param mappings 应用实例和服务单元获取连接映射信息
     * @return
     * @Date: 2019/8/21
     */
    public boolean update(String appInstanceId, List<SuDbMapping> mappings)
    {
        DataValidator.checkForEmptyString(appInstanceId, "appInstanceId");
        DataValidator.checkForNullReference(mappings, "List<SUDBMapping>");

        String cacheKey = this.getCacheKey(appInstanceId);
        this.repository.saveAll(mappings);

        for (SuDbMapping item : mappings)
        {
            tenantCache.hashRemove(cacheKey, item.getSu());
        }

        return true;
    }

    /**
     * 删除
     *
     * @param appInstanceId 应用实例
     * @return
     * @Date: 2019/8/21
     */
    public boolean removeByAppInstanceId(String appInstanceId)
    {
        DataValidator.checkForEmptyString(appInstanceId, "appInstanceId");

        List<SuDbMapping>  mappings = this.getAll(appInstanceId);
        if (mappings != null)
        {
            String cacheKey = this.getCacheKey(appInstanceId);
            this.repository.deleteAll(mappings);

            for (var item : mappings)
            {
                tenantCache.hashRemove(cacheKey, item.getSu());
            }
        }

        return true;
    }

    /**
     * 删除
     *
     * @Date: 2019/8/21
     */
    public boolean removeFromCache(String tenantId)
    {
        DataValidator.checkForEmptyString(tenantId, "tenantId");
        String cacheKey = this.getCacheKey(tenantId);
        tenantCache.remove(cacheKey);
        return true;
    }

    /**
     * 根据租户标识获取缓存key
     *
     * @param appInstanceId 应用实例
     * @return
     * @Date: 2019/8/21
     */
    private String getCacheKey(String appInstanceId)
    {
        return String.format("map_%s", appInstanceId);
    }
}
